#include "dialogs/DialogControls.h"

#include "scenes/SceneMainMenu.h"
#include "dialogs/DialogOptions.h"

#define TOP_OFFSET 30
#define TEXT_OFFSET 2

DialogControls::DialogControls( GameApplication& theApp, gdn::Scene& theScene )
   : App( theApp ),
     Scene( theScene )
{
	// None
}

void DialogControls::Initialize()
{
	App.GameConfig.LoadFromFile();

	background.SetImage( *App.Images.GetResource( App.GameResources[ "gui dialog background" ] ) );

	rouletteLeft   = App.Images.GetResource( App.GameResources[ "gui button left" ] );
	rouletteMiddle = App.Images.GetResource( App.GameResources[ "gui roulette control" ] );
	rouletteRight  = App.Images.GetResource( App.GameResources[ "gui button right" ] );
	font           = App.Fonts.GetResource ( App.GameResources[ "font sansation" ] );

	gdn::Image* closeImage = App.Images.GetResource( App.GameResources[ "gui button small" ] );

	std::vector< std::string > options;
	options.push_back( "Up" );
	options.push_back( "Left" );
	options.push_back( "Right" );
	options.push_back( "Down" );
	options.push_back( "B" );
	options.push_back( "X" );
	options.push_back( "A" );
	options.push_back( "Y" );
	options.push_back( "L" );
	options.push_back( "R" );

	#ifndef BUILD_GP2X_WIZ
		options.push_back( "M" );
		options.push_back( "S" );
	#else
		options.push_back( "Menu" );
		options.push_back( "Select" );
	#endif


	controls.push_back( std::vector< std::pair< gdn::Text, gui::Roulette > >() );
	controls.push_back( std::vector< std::pair< gdn::Text, gui::Roulette > >() );
	currentPage = 0;


	// Page 1
	AddItem( controls[ 0 ], gdn::Vector2f( 10,  25 + TOP_OFFSET ), "Jump: ",  options, FindCorrespondingIndex( options, App.GameConfig.GetJumpKey() ), 45 );
	AddItem( controls[ 0 ], gdn::Vector2f( 10,  50 + TOP_OFFSET ), "Left: ",  options, FindCorrespondingIndex( options, App.GameConfig.GetWalkLeftKey() ), 45 );
	AddItem( controls[ 0 ], gdn::Vector2f( 10,  75 + TOP_OFFSET ), "Right: ", options, FindCorrespondingIndex( options, App.GameConfig.GetWalkRightKey() ), 45 );
	AddItem( controls[ 0 ], gdn::Vector2f( 10, 100 + TOP_OFFSET ), "Down: ",  options, FindCorrespondingIndex( options, App.GameConfig.GetCrouchKey() ), 45 );

	AddItem( controls[ 0 ], gdn::Vector2f( 120,  25 + TOP_OFFSET ), "Select Up: ",    options, FindCorrespondingIndex( options, App.GameConfig.GetSelectionUpKey() ), 80 );
	AddItem( controls[ 0 ], gdn::Vector2f( 120,  50 + TOP_OFFSET ), "Select Left: ",  options, FindCorrespondingIndex( options, App.GameConfig.GetSelectionLeftKey() ), 80 );
	AddItem( controls[ 0 ], gdn::Vector2f( 120,  75 + TOP_OFFSET ), "Select Right: ", options, FindCorrespondingIndex( options, App.GameConfig.GetSelectionRightKey() ), 80 );
	AddItem( controls[ 0 ], gdn::Vector2f( 120, 100 + TOP_OFFSET ), "Select Down: ",  options, FindCorrespondingIndex( options, App.GameConfig.GetSelectionDownKey() ), 80 );

	// Page 2
	AddItem( controls[ 1 ], gdn::Vector2f( 8,  25 + TOP_OFFSET ), "Run: ",    options, FindCorrespondingIndex( options, App.GameConfig.GetRunKey() ), 57 );

	AddItem( controls[ 1 ], gdn::Vector2f( 8,  50 + TOP_OFFSET ), "Pause: ",  options, FindCorrespondingIndex( options, App.GameConfig.GetPauseKey() ), 57 );

	AddItem( controls[ 1 ], gdn::Vector2f( 8,  75 + TOP_OFFSET ), "Look Up: ",    options, FindCorrespondingIndex( options, App.GameConfig.GetLookUpKey() ), 57 );
	AddItem( controls[ 1 ], gdn::Vector2f( 126, 25 + TOP_OFFSET ), "Look Down: ",  options, FindCorrespondingIndex( options, App.GameConfig.GetLookDownKey() ), 74 );
	AddItem( controls[ 1 ], gdn::Vector2f( 126, 50 + TOP_OFFSET ), "Look Left: ",  options, FindCorrespondingIndex( options, App.GameConfig.GetLookLeftKey() ), 74 );
	AddItem( controls[ 1 ], gdn::Vector2f( 126, 75 + TOP_OFFSET ), "Look Right: ", options, FindCorrespondingIndex( options, App.GameConfig.GetLookRightKey() ), 74 );


	std::vector< std::string > pages;
	pages.push_back( "Page 1" );
	pages.push_back( "Page 2" );
	controlPage = gui::Roulette( gdn::Vector2f( 105, 165 ), pages, 0,
					             *rouletteLeft, *rouletteRight, *rouletteMiddle, *font, 13, gdn::Color( 0, 0, 0 ),
					             gdn::Rectanglei( 0, 0, 7, 20 ), gdn::Rectanglei( 7, 0, 7, 20 ), gdn::Rectanglei( 14, 0, 7, 20 ),
					             gdn::Rectanglei( 0, 0, 7, 20 ), gdn::Rectanglei( 7, 0, 7, 20 ), gdn::Rectanglei( 14, 0, 7, 20 ) );


	closeButton = gui::Button( gdn::Vector2f( 244, 0 ),
							   "X", "X", "X",
							   gdn::Color( 0, 0, 0 ), gdn::Color( 0, 0, 0 ), gdn::Color( 255, 255, 255 ),
				               *closeImage, *font, 15,
				               gdn::Rectanglei( 0, 0, 24, 24 ), gdn::Rectanglei( 24, 0, 24, 24 ), gdn::Rectanglei( 48, 0, 24, 24 ) );
}

void DialogControls::Terminate()
{
	App.GameConfig.SetJumpKey( controls[ 0 ][ 0 ].second.GetCurrentItem() );
	App.GameConfig.SetWalkLeftKey( controls[ 0 ][ 1 ].second.GetCurrentItem()  );
	App.GameConfig.SetWalkRightKey( controls[ 0 ][ 2 ].second.GetCurrentItem()  );
	App.GameConfig.SetCrouchKey( controls[ 0 ][ 3 ].second.GetCurrentItem()  );

	App.GameConfig.SetSelectionUpKey( controls[ 0 ][ 4 ].second.GetCurrentItem()  );
	App.GameConfig.SetSelectionLeftKey( controls[ 0 ][ 5 ].second.GetCurrentItem()  );
	App.GameConfig.SetSelectionRightKey( controls[ 0 ][ 6 ].second.GetCurrentItem()  );
	App.GameConfig.SetSelectionUpKey( controls[ 0 ][ 7 ].second.GetCurrentItem()  );

	App.GameConfig.SetRunKey( controls[ 1 ][ 0 ].second.GetCurrentItem()  );

	App.GameConfig.SetPauseKey( controls[ 1 ][ 1 ].second.GetCurrentItem()  );

	App.GameConfig.SetLookUpKey( controls[ 1 ][ 2 ].second.GetCurrentItem()  );
	App.GameConfig.SetLookDownKey( controls[ 1 ][ 3 ].second.GetCurrentItem()  );
	App.GameConfig.SetLookLeftKey( controls[ 1 ][ 4 ].second.GetCurrentItem()  );
	App.GameConfig.SetLookRightKey( controls[ 1 ][ 5 ].second.GetCurrentItem()  );

	App.GameConfig.SaveToFile();
}

void DialogControls::Step( gdn::Event& Event )
{
	for ( unsigned int i = 0; i < controls[ currentPage ].size(); ++i )
	{
		controls[ currentPage ][ i ].second.Process( Event );
	}

	controlPage.Process( Event );
	if ( controlPage.GetCurrentItem() == "Page 1" )
	{
		currentPage = 0;
	}
	else if ( controlPage.GetCurrentItem() == "Page 2" )
	{
		currentPage = 1;
	}

	if ( closeButton.Process( Event ) == GUI_BUTTON_RELEASE )
	{
		static_cast< SceneMainMenu& >( Scene ).OpenDialog< DialogOptions >();
	}
}

void DialogControls::Draw( gdn::RenderImage& renderImage )
{
	renderImage.Clear();

	renderImage.Draw( background );

	for ( unsigned int i = 0; i < controls[ currentPage ].size(); ++i )
	{
		renderImage.Draw( controls[ currentPage ][ i ].first );
		controls[ currentPage ][ i ].second.Draw( renderImage );
	}

	controlPage.Draw( renderImage );

	closeButton.Draw( renderImage );

	renderImage.Display();
}

void DialogControls::AddItem( std::vector< std::pair< gdn::Text, gui::Roulette > >& page, const gdn::Vector2f& pos, const std::string& text, const std::vector< std::string >& options, unsigned int theDefault, float offset )
{
	gdn::Text textOption;
	gui::Roulette controlOption;

	textOption.SetColor( gdn::Color( 0, 0, 0 ) );
	textOption.SetFont( *font );
	textOption.SetCharacterSize( 13 );
	textOption.SetPosition( pos.x, pos.y + TEXT_OFFSET );
	textOption.SetString( text );
	controlOption = gui::Roulette( gdn::Vector2f( pos.x + offset, pos.y ), options, theDefault,
					               *rouletteLeft, *rouletteRight, *rouletteMiddle, *font, 13, gdn::Color( 0, 0, 0 ),
					               gdn::Rectanglei( 0, 0, 7, 20 ), gdn::Rectanglei( 7, 0, 7, 20 ), gdn::Rectanglei( 14, 0, 7, 20 ),
					               gdn::Rectanglei( 0, 0, 7, 20 ), gdn::Rectanglei( 7, 0, 7, 20 ), gdn::Rectanglei( 14, 0, 7, 20 ) );
	page.push_back( std::pair< gdn::Text, gui::Roulette >( textOption, controlOption ) );
}

size_t DialogControls::FindCorrespondingIndex( const std::vector< std::string >& vector, const std::string& string )
{
	for ( size_t i = 0; i < vector.size(); ++i )
	{
		if ( vector[ i ] == string )
		{
			return i;
		}
	}

	return 0;
}
